
local HX = require "packages/huixiangkill/hxfs"

Fk:addMiniGame {
  name = "ChooseGeneralWithCanChange",
  qml_path = "packages/huixiangkill/qml/ChooseGeneralWithCanChange",
  default_choice = function(player, data) --默认值
    return table.random(data.cards, data.num)
  end,
  update_func = function(player, data)
    player:doNotify("UpdateMiniGame", data)
  end,
}

Fk:loadTranslationTable{
  ["time limitation: 30 s"] = "游戏时长达到30秒",
  ["Change General"] = "换将(剩%1次)",
  ["#hx__role_aquire_fourSymbols"] = "%from 获得了 %arg 标记"
}

local role_getlogic = function()
  local role_logic = GameLogic:subclass("hx__role_logic")

  function role_logic:initialize(room)
    GameLogic.initialize(self, room)
    self.role_table = {
      { "lord" },
      { "lord", "rebel" },
      { "lord", "rebel", "renegade" },
      { "lord", "loyalist", "rebel", "renegade" },
      { "lord", "loyalist", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "renegade" },
      { "lord", "loyalist", "loyalist", "loyalist", "rebel", "rebel", "rebel", "rebel", "rebel", "renegade" },
    }
  end

  function role_logic:assignRoles()
    local room = self.room
    local n = #room.players
    local roles = self.role_table[n]
    table.shuffle(roles)

    for i = 1, n do
      local p = room.players[i]
      p.role = roles[i]
    end

    local function getPlayerByScreenName(Room, name)
      return table.find(Room.players, function(p)
        return p._splayer:getScreenName() == name
      end)
    end

    local croom = room.room
    local cowner = croom:getOwner()
    local owner = getPlayerByScreenName(room, cowner:getScreenName())
    if #table.filter(room.players, function(p) return p.id > 0 end) == 1 then  --只有一名玩家时可以自选身份
      local allrole = {}
      local oldrole = owner.role
      for _, r in ipairs(roles) do
        table.insertIfNeed(allrole, r)
      end
      table.insert(allrole, "Cancel")
      local truerole = room:askToChoice(owner, {
        choices = allrole,
        skill_name = "game_rule",
        prompt = "#hx__choose_role",
        cancelable = true,
      })
      if truerole and truerole ~= "Cancel" then
        owner.role = truerole
        for _, p in ipairs(room.players) do
          if p.role == owner.role and p.id ~= owner.id then
            p.role = oldrole
            break
          end
        end
      end
    end

    for i = 1, n do
      local p = room.players[i]
      if p.role == "lord" then
        room:setPlayerProperty(p, "role_shown", true)
      end
      room:broadcastProperty(p, "role")
    end
  end

  --- 分配座位
  function role_logic:adjustSeats()
    local player_circle = {}
    local players = self.room.players
    local p = 1
    for i = 1, #players do
      if players[i].role == "lord" then
        p = i
        break
      end
    end
    for j = p, #players do
      table.insert(player_circle, players[j])
    end
    for j = 1, p - 1 do
      table.insert(player_circle, players[j])
    end

    local owner = table.filter(self.room.players, function(pid) return pid.id > 0 end)
    if #owner == 1 then  --自选座位
      owner = owner[1]
      if owner.role ~= "lord" then
        local choices = {}
        for i = 1, #players do
          choices[i] = tostring(i).."号位"
        end
        table.removeOne(choices, "1号位")
        table.insert(choices, "Cancel")
        local seat = self.room:askToChoice(owner, {
          choices = choices,
          skill_name = "game_rule",
          prompt = "#hx__choose_seat",
          cancelable = true,
        })
        if seat and seat ~= "Cancel" then
          local seatNum = tonumber(string.sub(seat, 1, 1)) or math.random(2, #player_circle)
          local oldp = player_circle[seatNum]
          local oldseat
          for i = 1, #player_circle do
            if player_circle[i].id == owner.id then
              oldseat = i
            end
          end
          player_circle[seatNum] = owner
          player_circle[oldseat] = oldp
        end
      end
    end

    self.room:arrangeSeats(player_circle)
  end

  function role_logic:chooseGenerals()
    local room = self.room ---@class Room
    -- 备选武将卡数
    local generalNum = room:getSettings("generalNum")
    -- 选卡数（主要是是否有副将）
    local n = room:getSettings("enableDeputy") and 2 or 1
    local lord = room:getLord()

    if lord ~= nil then
      room:setCurrent(lord)
      local a1 = #room.general_pile
      local a2 = #room.players * generalNum
      if a1 < a2 then
        room:sendLog{
          type = "#NoEnoughGeneralDraw",
          arg = a1,
          arg2 = a2,
          toast = true,
        }
        room:gameOver("")
      end

      -- 换将卡数量
      local change_num = room:getSettings("changeGeneralNum") or 0
      -- 后置位额外换将卡
      local extra_change_num = room:getSettings("late_position_extraChange") or 0
      -- 后置位额外初始手牌
      local extra_hand_num = room:getSettings("late_position_initialHandcard") or 0
      -- 内奸额外换将卡
      local renegade_change_num = room:getSettings("renegadeExtraChange") or 0
      -- 常备主
      local lordNum = room:getSettings("lordNum") or 0
      -- 同名武将替换
      local convertGeneral = room:getSettings("convertGeneral") or false
      -- 四象标记
      local enableFourSymbols = room:getSettings("enableFourSymbols") or false

      -- 主公选将

      local lords = {}
      local lord = room:getLord()
      if(lord) then
        if lordNum > 0 then
          lords = table.random(table.map(HX.getGenerals(lordNum, nil, nil, function (g)
            return not table.contains(Fk.lords, g.name)
          end), function (g)
            return g.name
          end), lordNum)
        end
        local lord_generals = table.map(HX.getGenerals(generalNum, nil, lord), function (g)
          return g.name
        end)
        table.insertTable(lords, lord_generals)
        local lord_change = table.map(HX.getGenerals(change_num < #lords and change_num or #lords, nil, lords), function (g)
          return g.name
        end)
        local req = room:askToMiniGame({lord}, {
          skill_name = "AskForGeneral",
          game_type = "ChooseGeneralWithCanChange",
          data_table = {[lord.id] = {
            cards = lords,
            num = n,
            change = lord_change,
            no_c = not convertGeneral,
            heg = false,
            type = "askForGeneralsChosen",
            extra = {n = n}, 
          }},  
          timeout = self.room:getSettings("generalTimeout"),
        })
        local lord_result = req:getResult(lord)
        local lord_general2 = lord_result[1]
        local lord_deputy = lord_result[2]
        room:prepareGeneral(lord, lord_general2, lord_deputy, true)

        room:askToChooseKingdom({lord})
        room:broadcastProperty(lord, "kingdom")
        
        local canAttachSkill = function(player, skillName)
          local skill = Fk.skills[skillName]
          if not skill then
            fk.qCritical("Skill: "..skillName.." doesn't exist!")
            return false
          end
          if skill:hasTag(Skill.Lord) and not (player.role == "lord" and player.role_shown and room:isGameMode("hx__role_mode")) then
            return false
          end

          if skill:hasTag(Skill.AttachedKingdom) and not table.contains(skill:getSkeleton().attached_kingdom, player.kingdom) then
            return false
          end

          return true
        end

        local lord_skills = {}
        for _, s in ipairs(Fk.generals[lord.general].skills) do
          if canAttachSkill(lord, s.name) then
            table.insertIfNeed(lord_skills, s.name)
          end
        end
        for _, sname in ipairs(Fk.generals[lord.general].other_skills) do
          if canAttachSkill(lord, sname) then
            table.insertIfNeed(lord_skills, sname)
          end
        end

        local deputyGeneral = Fk.generals[lord.deputyGeneral]
        if deputyGeneral then
          for _, s in ipairs(deputyGeneral.skills) do
            if canAttachSkill(lord, s.name) then
              table.insertIfNeed(lord_skills, s.name)
            end
          end
          for _, sname in ipairs(deputyGeneral.other_skills) do
            if canAttachSkill(lord, sname) then
              table.insertIfNeed(lord_skills, sname)
            end
          end
        end
        for _, skill in ipairs(lord_skills) do
          room:doBroadcastNotify("AddSkill", {
            lord.id,
            skill
          })
        end

        if enableFourSymbols then
          local player = lord
          local mark_type = math.random(4)
          local mark_name_table = {
            "azure_dragon",
            "white_tiger",
            "vermilion_bird",
            "black_tortoise"
          }
          room:doSuperLightBox("packages/huixiangkill/qml/DivineBeastFly.qml", {playerId = player.id, beastType = mark_type - 1})
          room:delay(1700)
          room:sendLog{
            type = "#hx__role_aquire_fourSymbols",
            from = player.id,
            arg = "@!!"..mark_name_table[mark_type],
          }
          room:setPlayerMark(player, "@!!"..mark_name_table[mark_type], 1)
          player:addFakeSkill("hx__"..mark_name_table[mark_type].. "&")
          player:prelightSkill("hx__"..mark_name_table[mark_type].. "&", true)
        end
      end

      local all_generals = {}
      local data_table = {}
      local to_choose = {}
      for _, player in ipairs(room.players) do
        if player.role ~= "lord" then
          table.insert(to_choose, player)
          local p_change_num = change_num
          if player.seat >= 8 then
            p_change_num = p_change_num + extra_change_num
          end
          if player.role == "renegade" then
            p_change_num = p_change_num + renegade_change_num
          end
          local generals = table.map(HX.getGenerals(generalNum, nil, all_generals), function (g)
            return g.name
          end)
          p_change_num = p_change_num < #generals and p_change_num or #generals
          table.insertTable(all_generals, generals)
          local changes = table.map(HX.getGenerals(p_change_num, nil, all_generals), function (g)
            return g.name
          end)
          table.insertTable(all_generals, changes)
          data_table[player.id] = {
            cards = generals,
            num = n,
            change = changes,
            no_c = not convertGeneral,
            heg = false,
            type = "askForGeneralsChosen",
            extra = {n = n},
          }
        elseif player.role == "lord" then
          table.insert(all_generals, player.general)
          if player.deputyGeneral ~= "" then
            table.insert(all_generals, player.deputyGeneral)
          end
        end
      end
      local req = room:askToMiniGame(to_choose, {
        skill_name = "AskForGeneral",
        game_type = "ChooseGeneralWithCanChange",
        data_table = data_table,
        timeout = self.room:getSettings("generalTimeout"),
      })

      for _, p in ipairs(to_choose) do
        local p_result = req:getResult(p)
        local general = p_result[1]
        local deputy = p_result[2]
        room:prepareGeneral(p, general, deputy)
      end

      room:askToChooseKingdom(to_choose)

      for _, p in ipairs(to_choose) do
        room:broadcastProperty(p, "general")
        room:broadcastProperty(p, "deputyGeneral")
      end
    end
  end

  return role_logic
end

local role_mode = fk.CreateGameMode{
  name = "hx__role_mode",
  minPlayer = 2,
  maxPlayer = 10,
  logic = role_getlogic,
  rule = "#hx__role_rule&",
  main_mode = "role_mode",
  is_counted = function(self, room)
    return #room.players >= 5
  end,
  surrender_func = function(self, playedTime)
    local roleCheck = false
    local roleText = ""
    local alive_players = table.filter(Fk:currentRoom().players, function(p)
      return not p.dead or p.rest > 0
    end)
    if Self.role == "renegade" then
      roleCheck = not table.find(alive_players, function(p)
        return p ~= Self and table.contains({"rebel", "rebel_chief", "renegade"}, p.role)
      end)
      roleText = "left lord and loyalist alive"
    elseif Self.role == "rebel" or Self.role == "rebel_chief" then
      roleCheck = #table.filter(alive_players, function(p)
        return table.contains({"rebel", "rebel_chief"}, p.role)
      end) == 1
      roleText = "left one rebel alive"
    else
      if Self.role == "loyalist" or Self.role == "civilian" then
        return { { text = Self.role.." never surrender", passed = false } }
      else
        if #alive_players < 3 then
          roleCheck = true
        else
          roleText = "left you alive"
          local left_loyalist, left_rebel, left_renegade = false, false, false
          for _, p in ipairs(alive_players) do
            if p ~= Self then
              if table.contains({"lord", "loyalist"}, p.role) then
                left_loyalist = true
                break
              else
                if table.contains({"rebel", "rebel_chief"}, p.role) then
                  left_rebel = true
                elseif p.role == "renegade" then
                  left_renegade = true
                end
              end
            end
          end
          if left_loyalist then
            roleCheck = false
          else
            roleCheck = not (left_rebel and left_renegade)
          end
        end
      end
    end

    return {
      { text = "time limitation: 2 min", passed = playedTime >= 120 },
      { text = roleText, passed = roleCheck },
    }
  end,
}

Fk:loadTranslationTable{
  ["change_general_num"] = "换将卡数量",

  ["convertGeneral"] = "同名武将替换",
  ["#convertGeneral"] = "可以将武将替换为同名武将的其他版本",

  ["lordNum"] = "常备主",
  ["#lordNum"] = "主公额外的主公将",

  ["enableFourSymbols"] = "四象标记",
  ["#enableFourSymbols"] = "是否开启四象标记，详见游戏模式内注解",
  ["lord_exrta_maxHandcard"] = "主公额外手牌上限",
  ["renegadeExtraChange"] = "内奸额外换将卡数",
  ["renegadeComeBackToLifeCompensation"] = "内奸复活补偿",
  ["#renegadeComeBackToLifeCompensation"] = "内奸失救时，可以亮出身份牌并将体力恢复至1。",
  
  ["late_position_initialHandcard"] = "后置位额外初始手牌数",
  ["late_position"] = "后置位：八号位及以后",
  ["late_position_extraChange"] = "后置位额外换将卡数量",
}

local W = require "ui_emu.preferences"

role_mode.ui_settings = {
  W.PreferenceGroup{
    W.SwitchRow{
      _settingsKey = "convertGeneral",
      title = "convertGeneral",
      subTitle = Fk:translate("#convertGeneral", Config.language)
    },
    W.SpinRow{
      from = 0,
      to = 4,
      _settingsKey = "changeGeneralNum",
      title = "change_general_num"
    },
    W.SpinRow{
      from = 0,
      to = 4,
      title = "lordNum",
      _settingsKey = "lordNum",
      subTitle = Fk:translate("#lordNum", Config.language)
    }
  },
  W.PreferenceGroup{
    W.SwitchRow{
      _settingsKey = "enableFourSymbols",
      title = "enableFourSymbols",
      subTitle = Fk:translate("#enableFourSymbols", Config.language)
    },
    W.SpinRow{
       from = 0,
       to = 4,
      _settingsKey = "lord_extra_maxHancard",
      title = "lord_exrta_maxHandcard"
    },
    W.SpinRow{
      from = 0,
      to = 4,
      _settingsKey = "renegadeExtraChange",
      title = "renegadeExtraChange"
    },
    W.SwitchRow{
      _settingsKey = "renegadeComeBackToLife",
      title = "renegadeComeBackToLifeCompensation",
      subTitle = Fk:translate("#renegadeComeBackToLifeCompensation", Config.language)
    }
  },
  W.PreferenceGroup{
    W.SpinRow{
      from = 0,
      to = 4,
      _settingsKey = "late_position_initialHandcard",
      title = "late_position_initialHandcard",
      subTitle = Fk:translate("late_position", Config.language)
    },
    W.SpinRow{
      from = 0,
      to = 8,
      _settingsKey = "late_position_extraChange",
      title = "late_position_extraChange",
      subTitle = Fk:translate("late_position", Config.language)
    }
  }
}

Fk:loadTranslationTable{
  ["time limitation: 2 min"] = "游戏时长达到2分钟",
  ["#hx_role-generalnum"] = "请选择可多选的武将数，将取所有非人机玩家选项的平均值（向下取整）",
  ["#hx__choose_role"] = "你可以自选自己的身份，点取消则为随机",
  ["#hx__choose_seat"] = "你可以自选自己的座位，点取消则为随机",
  ["hx__role_mode"] = "多人身份",

  [":hx__role_mode"] = [========================================[
## 多人身份模式简介

至多10人的身份模式，同时加入了换将卡。身份分配参考下表：


| 玩家人数 | 主公 | 忠臣 | 反贼 | 内奸 |
| -------- | ---- | ---- | ---- | ---- |
| 2        | 1    | 0    | 1    | 0    |
| 3        | 1    | 0    | 1    | 1    |
| 4        | 1    | 1    | 1    | 1    |
| 5        | 1    | 1    | 2    | 1    |
| 6        | 1    | 1    | 3    | 1    |
| 7        | 1    | 2    | 3    | 1    |
| 8        | 1    | 2    | 4    | 1    |
| 9        | 1    | 3    | 4    | 1    |
| 10        | 1    | 3    | 4    | 2    |


### 另外，如果仅有一名真人，则可以自选身份和座位。

### 四象标记

#### ☆ 所有选手亮将结束后，主公须在四张四象牌中抽取一张获得，并获得对应四象技能。
#### ☆ 发动四象技能后失去四象牌。一名角色的回合结束后，若反贼全部阵亡，亦失去四象牌。

##### 朱雀
出牌阶段，你可以弃置一张非基本牌，对一名角色造成1点伤害。以此法杀死反贼不执行奖惩。

##### 玄武
你可以将一张牌当【桃】使用。

##### 青龙
回合开始时，你可以弃置两张牌，弃置你判定区里的一张【乐不思蜀】或【兵粮寸断】。

##### 白虎
你可以将一张牌当【杀】或【闪】使用或打出。

  ]========================================],
}



return role_mode
